"""
用户模块后端接口
包含用户注册登录、收藏管理、评论点赞等核心功能
"""
from flask import request, jsonify, current_app
from functools import wraps
from datetime import datetime
import re
import jwt
from passlib.hash import argon2
from sqlalchemy.orm import aliased
from models import db, User, Image, ImageVersion, UserCollect, CollectItem, UserAction,AdminAction

# ----------------- 辅助函数 -----------------
def validate_phone(phone):
    """验证中国大陆手机号格式（11位数字且以1开头）"""
    return re.match(r"^1[3-9]\d{9}$", phone) is not None

def generate_token(user_id):
    """生成JWT令牌"""
    return jwt.encode(
        {'user_id': user_id, 'exp': datetime.utcnow() + current_app.config['JWT_EXPIRATION']},
        current_app.config['SECRET_KEY'],
        algorithm='HS256'
    )

def token_required(f):
    """身份验证装饰器"""
    @wraps(f)
    def decorated(*args, **kwargs):
        # 测试模式处理
        if current_app.config['TESTING_MODE']:
            user_id = request.args.get('user_id')
            if not user_id:
                return jsonify({'error': '测试模式需要user_id参数'}), 401
            user = User.query.get(user_id)
            if not user:
                return jsonify({'error': '用户不存在'}), 404
            request.user = user
            return f(*args, **kwargs)
        
        # 正式环境验证
        token = request.headers.get('Authorization')
        if not token:
            return jsonify({'error': '缺少访问令牌'}), 401
        try:
            data = jwt.decode(token, current_app.config['SECRET_KEY'], algorithms=['HS256'])
            user = User.query.get(data['user_id'])
            if not user:
                raise ValueError('用户不存在')
            request.user = user
        except jwt.ExpiredSignatureError:
            return jsonify({'error': '令牌已过期'}), 401
        except Exception as e:
            return jsonify({'error': f'无效令牌: {str(e)}'}), 401
        return f(*args, **kwargs)
    return decorated

# ----------------- 用户认证模块 -----------------
def register():
    """用户注册接口
    Request JSON示例:
    {
        "username": "testuser",
        "password": "Test@123",
        "phone_number": "13800138000"
    }
    """
    data = request.json
    required_fields = ['username', 'password', 'phone_number']
    
    # 参数验证
    if not all(field in data for field in required_fields):
        return jsonify({'error': '缺少必要字段'}), 400
    
    # 手机号格式验证
    if not validate_phone(data['phone_number']):
        return jsonify({'error': '手机号格式无效'}), 400

    # 唯一性检查
    if User.query.filter_by(user_name=data['username']).first():
        return jsonify({'error': '用户名已被占用'}), 409
    if User.query.filter_by(phone_number=data['phone_number']).first():
        return jsonify({'error': '手机号已注册'}), 409

    try:
        # 创建用户记录
        new_user = User(
            user_name=data['username'],
            phone_number=data['phone_number'],
            membership_type='member',
            create_at=datetime.now()
        )
        new_user.set_password(data['password'])
        db.session.add(new_user)
        db.session.commit()
        
        return jsonify({
            'user_id': new_user.user_id,
            'username': new_user.user_name,
            'membership_type': new_user.membership_type
        }), 201
    except Exception as e:
        db.session.rollback()
        return jsonify({'error': f'注册失败: {str(e)}'}), 500

def login():
    """用户登录接口
    Request JSON示例:
    {
        "username": "testuser",
        "password": "Test@123"
    }
    """
    data = request.json
    if 'username' not in data or 'password' not in data:
        return jsonify({'error': '需要用户名和密码'}), 400
    
    # 查询用户（支持用户名或手机号登录）
    user = User.query.filter(
        (User.user_name == data['username']) |
        (User.phone_number == data['username'])
    ).first()
    
    # 身份验证
    if not user or not user.check_password(data['password']):
        return jsonify({'error': '用户名或密码错误'}), 401
    
    return jsonify({
        'user_id': user.user_id,
        'username': user.user_name,
        'token': generate_token(user.user_id)
    }), 200

# ----------------- 图片模块 -----------------
def get_image_details(image_id):
    """获取图片详细信息
    GET /images/<image_id>
    """
    # 查询基础信息
    image = Image.query.get(image_id)
    if not image:
        return jsonify({'error': '图片不存在'}), 404

    # 获取所有版本
    versions = ImageVersion.query.filter_by(image_id=image_id)\
                   .order_by(ImageVersion.upload_at.desc()).all()

    # 获取关联评论
    comments = db.session.query(
        UserAction.action_id,
        UserAction.comment_context,
        UserAction.create_at,
        User.user_id,
        User.user_name
    ).join(User, UserAction.user_id == User.user_id)\
     .filter(UserAction.image_id == image_id, 
            UserAction.action_type == 'comment')\
     .order_by(UserAction.create_at.desc()).all()

    # 构建响应数据
    response = {
        'basic_info': {
            'image_id': image.image_id,
            'title': image.image_title,
            'description': image.image_description,
            'tags': list(filter(None, [image.image_tag1, image.image_tag2, image.image_tag3])),
            'statistics': {
                'likes': image.beliked or 0,
                'collections': image.becollected or 0,
                'comments': image.comment_time or 0
            }
        },
        'versions': [{
            'version_id': v.version_id,
            'oss_path': f'https://mjseed-code-image.oss-cn-beijing.aliyuncs.com/{mj_path}' 
                if (mj_path := v.oss_path.split('mjseed-code-image', 1)[-1]) 
                else v.oss_path,
            'status': v.audit_status,
            'upload_time': v.upload_at.isoformat()
        } for v in versions],
        'comments': [{
            'id': c.action_id,
            'content': c.comment_context,
            'time': c.create_at.isoformat(),
            'author': {
                'user_id': c.user_id,
                'username': c.user_name
            }
        } for c in comments]
    }

    # 添加Midjourney代码信息
    if image.midjourney_code:
        response['basic_info']['midjourney_code'] = image.midjourney_code
        response['basic_info']['code_copy_count'] = image.codecopy_time or 0

    return jsonify(response), 200

# ----------------- 收藏管理模块 -----------------
@token_required
def manage_collection():
    """收藏夹综合管理接口
    支持操作：
    - POST 创建收藏夹/添加收藏项
    - GET 查询收藏夹结构
    - DELETE 删除收藏夹/收藏项
    - PATCH 重命名收藏夹/收藏项
    """
    user = request.user

    # 创建操作
    if request.method == 'POST':
        data = request.json
        if not data:
            return jsonify({'error': '缺少请求体'}), 400
        
        # 创建新收藏夹
        if 'collect_name' in data:
            if not data['collect_name'].strip():
                return jsonify({'error': '收藏夹名称不能为空'}), 400
            
            try:
                new_collect = UserCollect(
                    user_id=user.user_id,
                    collect_name=data['collect_name'].strip()
                )
                db.session.add(new_collect)
                db.session.commit()
                return jsonify({
                    'collect_id': new_collect.usercollect_id,
                    'collect_name': new_collect.collect_name
                }), 201
            except Exception as e:
                db.session.rollback()
                return jsonify({'error': f'创建失败: {str(e)}'}), 500
        
        # 添加收藏项
        elif all(k in data for k in ('usercollect_id', 'image_id', 'items_name')):
            collect = UserCollect.query.filter_by(
                usercollect_id=data['usercollect_id'],
                user_id=user.user_id
            ).first()
            if not collect:
                return jsonify({'error': '收藏夹不存在或无权访问'}), 404
            
            try:
                new_item = CollectItem(
                    usercollect_id=data['usercollect_id'],
                    image_id=data['image_id'],
                    items_name=data['items_name'].strip()
                )
                db.session.add(new_item)
                db.session.commit()
                return jsonify({
                    'item_id': new_item.items_id,
                    'image_id': new_item.image_id,
                    'item_name': new_item.items_name
                }), 201
            except Exception as e:
                db.session.rollback()
                return jsonify({'error': f'添加失败: {str(e)}'}), 500
        
        else:
            return jsonify({'error': '缺少必要参数'}), 400

    # 查询操作
    elif request.method == 'GET':
        try:
            # 获取最新版本子查询
            latest_version_subq = db.session.query(
                ImageVersion.image_id,
                db.func.max(ImageVersion.upload_at).label('latest_upload')
            ).group_by(ImageVersion.image_id).subquery()

            # 主查询
            query = db.session.query(
                UserCollect.usercollect_id.label('collect_id'),
                UserCollect.collect_name,
                CollectItem.items_id,
                CollectItem.items_name,
                Image.image_id,
                Image.image_title,
                Image.image_description,
                ImageVersion.oss_path
            ).outerjoin(CollectItem, UserCollect.usercollect_id == CollectItem.usercollect_id)\
             .outerjoin(Image, CollectItem.image_id == Image.image_id)\
             .outerjoin(latest_version_subq, Image.image_id == latest_version_subq.c.image_id)\
             .outerjoin(ImageVersion, 
                (ImageVersion.image_id == latest_version_subq.c.image_id) &
                (ImageVersion.upload_at == latest_version_subq.c.latest_upload)
             ).filter(UserCollect.user_id == user.user_id)\
              .order_by(UserCollect.usercollect_id, CollectItem.items_id)

            results = query.all()
            
            # 结构化返回数据
            collections = {}
            for row in results:
                collect_id = row.collect_id
                if collect_id not in collections:
                    collections[collect_id] = {
                        'collect_id': collect_id,
                        'collect_name': row.collect_name,
                        'items': []
                    }
                
                if row.items_id:
                    item_data = {
                        'item_id': row.items_id,
                        'item_name': row.items_name,
                        'image': {
                            'image_id': row.image_id,
                            'title': row.image_title,
                            'description': row.image_description,
                            'oss_path': row.oss_path.split('mjseed-code-image/')[-1] if row.oss_path else None
                        }
                    }
                    collections[collect_id]['items'].append(item_data)

            return jsonify(list(collections.values())), 200
        except Exception as e:
            current_app.logger.error(f"收藏查询失败: {str(e)}")
            return jsonify({'error': '获取收藏数据失败'}), 500

    # 删除操作
    elif request.method == 'DELETE':
        target_id = request.args.get('id')
        target_type = request.args.get('type')
        
        if not target_id or not target_type:
            return jsonify({'error': '需要id和type参数'}), 400
        
        # 删除收藏夹
        if target_type == 'collect':
            collect = UserCollect.query.filter_by(
                usercollect_id=target_id,
                user_id=user.user_id
            ).first()
            if not collect:
                return jsonify({'error': '收藏夹不存在'}), 404
            
            try:
                CollectItem.query.filter_by(usercollect_id=target_id).delete()
                db.session.delete(collect)
                db.session.commit()
                return jsonify({'message': '收藏夹及内容已删除'}), 200
            except Exception as e:
                db.session.rollback()
                return jsonify({'error': f'删除失败: {str(e)}'}), 500
        
        # 删除收藏项
        elif target_type == 'item':
            item = CollectItem.query.get(target_id)
            if not item:
                return jsonify({'error': '收藏项不存在'}), 404
            
            collect = UserCollect.query.filter_by(
                usercollect_id=item.usercollect_id,
                user_id=user.user_id
            ).first()
            if not collect:
                return jsonify({'error': '无权操作'}), 403
            
            try:
                db.session.delete(item)
                db.session.commit()
                return jsonify({'message': '收藏项已删除'}), 200
            except Exception as e:
                db.session.rollback()
                return jsonify({'error': f'删除失败: {str(e)}'}), 500
        
        else:
            return jsonify({'error': '无效操作类型'}), 400

    # 重命名操作
    elif request.method == 'PATCH':
        data = request.json
        if not data:
            return jsonify({'error': '缺少请求体'}), 400

        # 更新收藏夹名称
        if 'collect_id' in data and 'new_name' in data:
            collect = UserCollect.query.filter_by(
                usercollect_id=data['collect_id'],
                user_id=user.user_id
            ).first()
            if not collect:
                return jsonify({'error': '收藏夹不存在'}), 404
            
            try:
                collect.collect_name = data['new_name'].strip()
                db.session.commit()
                return jsonify({
                    'collect_id': collect.usercollect_id,
                    'new_name': collect.collect_name
                }), 200
            except Exception as e:
                db.session.rollback()
                return jsonify({'error': f'更新失败: {str(e)}'}), 500

        # 更新收藏项名称
        elif 'item_id' in data and 'new_name' in data:
            item = CollectItem.query.get(data['item_id'])
            if not item:
                return jsonify({'error': '收藏项不存在'}), 404
            
            collect = UserCollect.query.filter_by(
                usercollect_id=item.usercollect_id,
                user_id=user.user_id
            ).first()
            if not collect:
                return jsonify({'error': '无权操作'}), 403
            
            try:
                item.items_name = data['new_name'].strip()
                db.session.commit()
                return jsonify({
                    'item_id': item.items_id,
                    'new_name': item.items_name
                }), 200
            except Exception as e:
                db.session.rollback()
                return jsonify({'error': f'更新失败: {str(e)}'}), 500

        else:
            return jsonify({'error': '需要collect_id/new_name或item_id/new_name参数'}), 400

# ----------------- 评论管理模块 -----------------
@token_required
def comment_management():
    """评论管理接口
    支持操作：
    - POST 发表评论
    - GET 获取用户评论
    - DELETE 删除评论
    """
    user = request.user

    # 发表评论
    if request.method == 'POST':
        data = request.json
        if 'image_id' not in data or 'comment' not in data:
            return jsonify({'error': '需要image_id和comment参数'}), 400
        
        try:
            new_comment = UserAction(
                user_id=user.user_id,
                action_type='comment',
                image_id=data['image_id'],
                comment_context=data['comment'],
                create_at=datetime.now()
            )
            db.session.add(new_comment)
            
            # 更新图片评论计数
            image = Image.query.get(data['image_id'])
            if image:
                image.comment_time = (image.comment_time or 0) + 1
                db.session.add(image)
            
            db.session.commit()
            return jsonify({
                'comment_id': new_comment.action_id,
                'content': new_comment.comment_context
            }), 201
        except Exception as e:
            db.session.rollback()
            return jsonify({'error': str(e)}), 500

    # 获取用户评论
    elif request.method == 'GET':
        try:
            latest_version_subq = db.session.query(
                ImageVersion.image_id,
                db.func.max(ImageVersion.upload_at).label('latest_upload')
            ).group_by(ImageVersion.image_id).subquery()

            comments = db.session.query(
                UserAction.action_id,
                UserAction.comment_context,
                UserAction.create_at,
                Image.image_id,
                Image.image_title,
                Image.image_description,
                ImageVersion.oss_path
            ).join(Image, UserAction.image_id == Image.image_id)\
             .join(latest_version_subq, Image.image_id == latest_version_subq.c.image_id)\
             .join(ImageVersion, 
                (ImageVersion.image_id == latest_version_subq.c.image_id) &
                (ImageVersion.upload_at == latest_version_subq.c.latest_upload)
             ).filter(UserAction.user_id == user.user_id,
                     UserAction.action_type == 'comment')\
              .order_by(UserAction.create_at.desc()).all()

            return jsonify([{
                'comment_id': c.action_id,
                'content': c.comment_context,
                'time': c.create_at.isoformat(),
                'image': {
                    'image_id': c.image_id,
                    'title': c.image_title,
                    'description': c.image_description,
                    'oss_path': f'https://mjseed-code-image.oss-cn-beijing.aliyuncs.com/{mj_path}'
                                if (mj_path := c.oss_path.split('mjseed-code-image', 1)[-1])
                                     else c.oss_path
                }
            } for c in comments]), 200
        except Exception as e:
            return jsonify({'error': f'查询失败: {str(e)}'}), 500
        
# ----------------- 评论管理模块-----------------
    # 删除用户评论
    elif request.method == 'DELETE':
        action_id = request.args.get('comment_id')
        if not action_id:
            return jsonify({'error': '需要评论ID'}), 400

        try:
            # 验证评论所有权
            comment = UserAction.query.filter_by(
                action_id=action_id,
                user_id=user.user_id,
                action_type='comment'
            ).first()
            
            if not comment:
                return jsonify({'error': '评论不存在或无权操作'}), 404

            # 删除评论并更新计数
            db.session.delete(comment)
            
            if comment.image_id:
                image = Image.query.get(comment.image_id)
                if image and image.comment_time > 0:
                    image.comment_time -= 1
                    db.session.add(image)
            
            db.session.commit()
            return jsonify({'message': '评论删除成功'}), 200
        except Exception as e:
            db.session.rollback()
            return jsonify({'error': f'删除失败: {str(e)}'}), 500

# ----------------- 管理员删除评论 -----------------
def admin_delete_comment(action_id):
    """管理员删除评论功能"""
    try:
        # 临时使用硬编码管理员ID（后面再换）
        TEMP_ADMIN_ID = 1
        
        # 查询评论是否存在
        comment = UserAction.query.filter_by(
            action_id=action_id,
            action_type='comment'
        ).first()
        if not comment:
            return jsonify({'error': '评论不存在'}), 404

        # 删除评论
        db.session.delete(comment)

        # 更新图片评论计数
        image = Image.query.get(comment.image_id)
        if image:
            current_count = image.comment_time or 0
            if current_count > 0:
                image.comment_time = current_count - 1

        # 记录管理员操作（使用现有admin_action_db）
        admin_action = AdminAction(
            admin_id=TEMP_ADMIN_ID,  # 硬编码管理员ID
            admin_operation='delete',
            operation_content=f"Deleted comment {action_id}"
        )
        db.session.add(admin_action)

        db.session.commit()
        
        return jsonify({
            'message': '评论删除成功',
            'admin_id': TEMP_ADMIN_ID,
            'deleted_comment_id': action_id
        }), 200
        
    except Exception as e:
        db.session.rollback()
        return jsonify({'error': str(e)}), 500

# ----------------- 点赞管理模块 -----------------
@token_required
def like_management():
    """点赞管理接口
    支持操作：
    ◦ POST 点赞图片
    ◦ DELETE 取消点赞
    """
    user = request.user
    data = request.json
    
    # 参数校验
    if 'image_id' not in data:
        return jsonify({'error': '需要image_id参数'}), 400
    image_id = data['image_id']
    
    # 获取图片记录
    image = Image.query.get(image_id)
    if not image:
        return jsonify({'error': '图片不存在'}), 404

    # 查询现有点赞记录
    existing_like = UserAction.query.filter_by(
        user_id=user.user_id,
        image_id=image_id,
        action_type='like'
    ).first()

    try:
        # 处理点赞操作
        if request.method == 'POST':
            if existing_like:
                return jsonify({'error': '不可重复点赞'}), 409
                
            new_like = UserAction(
                user_id=user.user_id,
                action_type='like',
                image_id=image_id,
                create_at=datetime.now()
            )
            db.session.add(new_like)
            image.beliked = (image.beliked or 0) + 1

        # 处理取消点赞
        elif request.method == 'DELETE':
            if not existing_like:
                return jsonify({'error': '未找到点赞记录'}), 404
                
            db.session.delete(existing_like)
            if image.beliked > 0:
                image.beliked -= 1

        # 提交事务
        db.session.add(image)
        db.session.commit()
        return jsonify({
            'message': '操作成功',
            'likes_count': image.beliked
        }), 200 if request.method == 'DELETE' else 201

    except Exception as e:
        db.session.rollback()
        return jsonify({'error': f'操作失败: {str(e)}'}), 500

@token_required
def get_user_likes():
    """获取用户点赞列表"""
    user = request.user
    
    try:
        latest_version_subq = db.session.query(
            ImageVersion.image_id,
            db.func.max(ImageVersion.upload_at).label('latest_upload')
        ).group_by(ImageVersion.image_id).subquery()

        likes = db.session.query(
            Image.image_id,
            Image.image_title,
            Image.image_description,
            ImageVersion.oss_path,
            UserAction.create_at
        ).join(UserAction, Image.image_id == UserAction.image_id)\
         .join(latest_version_subq, Image.image_id == latest_version_subq.c.image_id)\
         .join(ImageVersion, 
            (ImageVersion.image_id == latest_version_subq.c.image_id) &
            (ImageVersion.upload_at == latest_version_subq.c.latest_upload)
         ).filter(UserAction.user_id == user.user_id,
                 UserAction.action_type == 'like')\
          .order_by(UserAction.create_at.desc()).all()

        return jsonify([{
            'image_id': l.image_id,
            'title': l.image_title,
            'description': l.image_description,
            'oss_path': f'https://mjseed-code-image.oss-cn-beijing.aliyuncs.com/{l.oss_path.split("mjseed-code-image/")[-1]}',
            'liked_time': l.create_at.isoformat()
        } for l in likes]), 200
    except Exception as e:
        current_app.logger.error(f"获取点赞列表失败: {str(e)}")
        return jsonify({'error': '获取数据失败'}), 500
